const HOST_TO_DEVICE_DATA_START = 31;
const FIXED_PACKAGE_CRC_RESULT = 136;
const DefaultThreshold = 128;
const MaxEBVValue = 16383;
const SuperBitmapRLELength = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 24, 36, 48, 120];
const PCPDSF_RLEX_BITMAP = 16;
const PCPDSF_RLED_BITMAP = 64;
const PCPDSF_RLEC_BITMAP = 128;
var LineActionNone = 0;
const LineActionLine = 1;
const LineActionPrint = 2;
let grayThreshold;
let supportSuperBitmap;
let softwareFlags;
let mPrinterDPI;
let mPrinterWidth;
let mByteWidth;
let mLineCount;
let mLineBytes;
let mLineData;
let mPrevBytes;
let mPrevData;
let mSumLines;
let mSumPrints;
let mSumRLE_Xs;
let mSumRLE_Ds;
let mSumRLE_Cs;
let mSumRepeats;
let mRLEXSaved;
let mRLEDSaved;
let mRLECSaved;
let mArrayBitmap;

function pageStartData() {
  return [31, 32, 0, 136];
}

function pageEndData() {
  return [31, 40, 0, 136];
}

function pageWidthData(width) {
  width = Math.floor((width + 7) / 8);

  if (width >= 192) {
    return [31, 39, 2, 192 | width >>> 8, width & 255, 136];
  } else {
    return [31, 39, 1, width, 136];
  }
}

function pageHeightData(height) {
  if (height > 16383) {
    return [31, 38, 3, 192, height >>> 8, height & 255, 136];
  } else if (height >= 192) {
    return [31, 38, 2, 192 | height >>> 8, height & 255, 136];
  } else {
    return [31, 38, 1, height, 136];
  }
}

function settingGapTypeData(gapType) {
  return [31, 66, 1, gapType, 136];
}

function settingGapLengthData(gapLength) {
  if (gapLength > 16383) {
    return [31, 69, 3, 192, gapLength >>> 8, gapLength & 255, 136];
  } else if (gapLength >= 192) {
    return [31, 69, 2, 192 | gapLength >>> 8, gapLength & 255, 136];
  } else {
    return [31, 69, 1, gapLength, 136];
  }
}

function settingStrengthData(strength) {
  return [31, 67, 1, strength, 136];
}

function settingSpeedData(speed) {
  return [31, 68, 1, speed, 136];
}

function arrayWithParam(printParam) {
  console.log("【print】start--0")
  start(printParam);
  console.log("【print】start--1--print--0")
  print(printParam);
  console.log("【print】print--1")
  return end(printParam);
}

function arrayWithImage(pixelDatas, printerDPI, _0x1e6792, width, height, gapType, gapLength, printDarkness, printSpeed) {
  return arrayWithParam({
    "pixelDatas": pixelDatas,
    "printerDPI": printerDPI,
    "printerWidth": _0x1e6792,
    "width": width,
    "height": height,
    "gapType": gapType,
    "gapLength": gapLength,
    "printDarkness": printDarkness,
    "printSpeed": printSpeed
  });
}

function start(withParam) {
  mArrayBitmap = [];
  grayThreshold = withParam.grayThreshold == null ? 128 : withParam.grayThreshold;
  supportSuperBitmap = withParam.supportSuperBitmap == null ? true : withParam.supportSuperBitmap;
  softwareFlags = withParam.softwareFlags == null ? 16 | 64 : withParam.softwareFlags;
  LineActionNone = 1;
  mPrinterDPI = withParam.printerDPI == null ? 203 : withParam.printerDPI;
  mPrinterWidth = withParam.printerWidth == null ? 384 : withParam.printerWidth;
  mByteWidth = Math.floor((mPrinterWidth + 7) / 8);
  mLineCount = withParam.topMargin == null ? 0 : withParam.topMargin;
  mLineBytes = 0;
  mLineData = null;
  mPrevBytes = 0;
  mPrevData = null;
  mSumLines = 0;
  mSumPrints = 0;
  mSumRLE_Xs = 0;
  mSumRLE_Ds = 0;
  mSumRLE_Cs = 0;
  mSumRepeats = 0;
  mRLEXSaved = 0;
  mRLEDSaved = 0;
  mRLECSaved = 0;
  pushPackage(pageStartData());
  pushPackage(pageWidthData(withParam.width));
  pushPackage(pageHeightData(withParam.height));

  if (withParam.gapType >= 0) {
    pushPackage(settingGapTypeData(withParam.gapType));
  }

  if (withParam.gapLength > 0) {
    pushPackage(settingGapLengthData(withParam.gapLength));
  }

  if (withParam.printDarkness > 0) {
    pushPackage(settingStrengthData(withParam.printDarkness - 1));
  }

  if (withParam.printSpeed > 0) {
    pushPackage(settingSpeedData(withParam.printSpeed - 1));
  }
}

function print(withParam) {
  let wpPixelData = withParam.pixelDatas;

  let wpWidth = withParam.width;
  let wpHeight = withParam.height;

  let wpMinWidth = Math.min(wpWidth, mPrinterWidth);

  let _0x1c3883 = Math.floor((wpMinWidth + 7) / 8);

  for (let i = 0; i < wpHeight; ++i) {
    let allocData = allocIntArray(_0x1c3883);

    let _0x2226c7 = wpWidth * i * 4;

    let _0x52601d = 128;
    let allocStartIndex = 0;

    for (let j = 0; j < wpMinWidth; ++j) {
      let _0x1dc39f = wpPixelData[_0x2226c7 + 0];
      let _0x424762 = wpPixelData[_0x2226c7 + 1];
      let _0x252955 = wpPixelData[_0x2226c7 + 2];
      let _0x2c5be6 = wpPixelData[_0x2226c7 + 3];

      if (_0x2c5be6 > 0) {
        let _0x543800 = _0x1dc39f * 0.3 + _0x424762 * 0.59 + _0x252955 * 0.11;

        if (_0x543800 <= grayThreshold) {
          allocData[allocStartIndex] = allocData[allocStartIndex] | _0x52601d;
        }
      }

      if (_0x52601d === 1) {
        _0x52601d = 128;
        ++allocStartIndex;
      } else {
        _0x52601d = _0x52601d >>> 1;
      }

      _0x2226c7 += 4;
    }

    printRow(allocData);
  }
}

function end(_0x1c7c66) {
  let _0x22b688 = _0x1c7c66.bottomMargin == null ? 0 : _0x1c7c66.bottomMargin;

  switch (LineActionNone) {
    case 1:
      pushLine(mLineCount + _0x22b688);
      break;

    case 2:
      pushPrint();
      pushLine(_0x22b688);
      break;

    default:
      return null;
  }

  LineActionNone = LineActionNone;
  pushPackage(pageEndData());
  return mArrayBitmap;
}

function printRow(_0x50fb56) {
  let _0x38639b = _0x50fb56.length - 1;

  for (; _0x38639b >= 0; --_0x38639b) {
    if (_0x50fb56[_0x38639b] !== 0) break;
  }

  if (_0x38639b < 0) {
    return printLine(1);
  }

  ++_0x38639b;

  switch (LineActionNone) {
    case 1:
      pushLine(mLineCount);
      break;

    case 2:
      if (mLineBytes === _0x38639b && checkArrayEquals(mLineData, _0x50fb56, _0x38639b)) {
        mLineCount += 1;
        return true;
      }

      pushPrint();
      break;

    default:
      return false;
  }

  mLineData = _0x50fb56;
  mLineBytes = _0x38639b;
  mLineCount = 1;
  LineActionNone = 2;
  return true;
}

function printLine(_0x5d757b) {
  switch (LineActionNone) {
    case 1:
      mLineCount += _0x5d757b;
      return true;

    case 2:
      pushPrint();
      break;

    default:
      return false;
  }

  mLineData = null;
  mLineBytes = 0;
  mLineCount = _0x5d757b;
  LineActionNone = 1;
  return true;
}

function pushLine(_0x1eb1c2) {
  if (_0x1eb1c2 <= 0) return;
  mSumLines += _0x1eb1c2;
  mPrevData = null;
  mPrevBytes = 0;
  let _0x3ddc42 = [27, 74, 255];

  for (; _0x1eb1c2 >= 255; _0x1eb1c2 -= 255) {
    pushPackage(_0x3ddc42);
  }

  if (_0x1eb1c2 > 0) {
    pushPackage([27, 74, _0x1eb1c2]);
  }
}

function pushPrint() {
  if (mLineCount <= 0) return;
  let _0x4cebbf = 0;

  for (; _0x4cebbf < mLineBytes; ++_0x4cebbf) {
    if (mLineData[_0x4cebbf] !== 0) break;
  }

  let _0x4d94a2 = mLineBytes - _0x4cebbf;

  let _0x2159f9 = null;
  let _0x4e6a46 = null;
  let _0x47a266 = null;
  let _0x37cf18 = 0;
  let _0x128300 = 0;
  let _0x35b619 = 0;

  if (supportSuperBitmap) {
    if ((softwareFlags & 128) !== 0) {
      _0x2159f9 = allocIntArray(mByteWidth + 4);
      _0x37cf18 = calcRLEC(mLineData, mLineBytes, _0x2159f9);
    }

    if ((softwareFlags & 16) !== 0) {
      _0x4e6a46 = allocIntArray(mByteWidth + 4);
      _0x128300 = calcRLEX(mLineData, mLineBytes, _0x4e6a46);
    }

    if ((softwareFlags & 64) !== 0 && mPrevData !== null) {
      _0x47a266 = allocIntArray(mByteWidth + 4);
      _0x35b619 = calcRLED(mPrevData, mPrevBytes, mLineData, mLineBytes, _0x47a266);
    }
  }

  let _0x8d137d = (_0x4cebbf >= 192 ? 4 : 3) + (_0x4d94a2 >= 192 ? 2 : 1) + _0x4d94a2;

  let _0x22f644 = _0x37cf18 <= 0 ? mByteWidth + 100 : _0x37cf18 + (_0x37cf18 >= 192 ? 4 : 3);

  let _0x1c3c76 = _0x128300 <= 0 ? mByteWidth + 100 : Math.floor((_0x128300 * 5 + 7) / 8) + (_0x128300 >= 192 ? 4 : 3);

  let _0x127de0 = _0x35b619 <= 0 ? mByteWidth + 100 : Math.floor((_0x35b619 * 5 + 7) / 8) + (_0x35b619 >= 192 ? 4 : 3);

  if (_0x22f644 < _0x8d137d && _0x22f644 <= _0x1c3c76 && _0x22f644 <= _0x127de0) {
    mSumRLE_Cs += 1;
    mRLECSaved += _0x8d137d - _0x22f644;
    pushRLEC(41, _0x2159f9, _0x37cf18);
  } else if (_0x1c3c76 < _0x8d137d && _0x1c3c76 <= _0x127de0) {
    mSumRLE_Xs += 1;
    mRLEXSaved += _0x8d137d - _0x1c3c76;
    pushRLEXD(44, _0x4e6a46, _0x128300);
  } else if (_0x127de0 < _0x8d137d) {
    mSumRLE_Ds += 1;
    mRLEDSaved += _0x8d137d - _0x127de0;
    pushRLEXD(45, _0x47a266, _0x35b619);
  } else {
    mSumPrints += 1;
    let _0x296dc5 = [31, 43, 0, 0];

    let _0x592f65 = pushEBV(_0x296dc5, 2, _0x4cebbf);

    _0x592f65 = pushEBV(_0x296dc5, _0x592f65, _0x4d94a2);
    pushPackage2(_0x296dc5, 0, _0x592f65, mLineData, _0x4cebbf, mLineBytes);
  }

  if (mLineCount > 1) {
    pushRepeat(mLineCount - 1);
  }

  mPrevData = mLineData;
  mPrevBytes = mLineBytes;
}

function pushRepeat(_0x36285e) {
  if (_0x36285e <= 0) return;
  mSumRepeats += _0x36285e;
  let _0x377396 = [31, 46, 0];
  pushEBV(_0x377396, 2, 16383);

  for (; _0x36285e > 16383; _0x36285e -= 16383 + 1) {
    pushPackage(_0x377396);
  }

  if (_0x36285e > 0) {
    _0x377396 = [31, 46, 0];
    pushEBV(_0x377396, 2, _0x36285e - 1);
    pushPackage(_0x377396);
  }
}

function pushRLEC(_0x3eda6e, _0x5ccfe2, _0x227ee5) {
  if (_0x227ee5 <= 0) return;
  let _0xa0212a = [31, _0x3eda6e, 0];

  let _0x48f55c = pushEBV(_0xa0212a, 2, _0x227ee5);

  pushPackage2(_0xa0212a, 0, _0x48f55c, _0x5ccfe2, 0, _0x227ee5);
}

function appendRLEC(_0x89c592, _0x2304ae, _0x1c8c60, _0xfbaebd) {
  for (; _0xfbaebd >= 63; _0xfbaebd -= 63) {
    if (_0x2304ae.value + 2 > mByteWidth) return false;
    _0x89c592[_0x2304ae.value] = 255;
    ++_0x2304ae.value;
    _0x89c592[_0x2304ae.value] = _0x1c8c60;
    ++_0x2304ae.value;
  }

  switch (_0xfbaebd) {
    case 1:
      if (_0x1c8c60 > 192) {
        if (_0x2304ae.value + 2 > mByteWidth) return false;
        _0x89c592[_0x2304ae.value] = 193;
        ++_0x2304ae.value;
        _0x89c592[_0x2304ae.value] = _0x1c8c60;
        ++_0x2304ae.value;
      } else {
        if (_0x2304ae.value + 1 > mByteWidth) return false;
        _0x89c592[_0x2304ae.value] = _0x1c8c60;
        ++_0x2304ae.value;
      }

      break;

    case 2:
      if (_0x2304ae.value + 2 > mByteWidth) return false;

      if (_0x1c8c60 > 192) {
        _0x89c592[_0x2304ae.value] = 194;
        ++_0x2304ae.value;
        _0x89c592[_0x2304ae.value] = _0x1c8c60;
        ++_0x2304ae.value;
      } else {
        _0x89c592[_0x2304ae.value] = _0x1c8c60;
        ++_0x2304ae.value;
        _0x89c592[_0x2304ae.value] = _0x1c8c60;
        ++_0x2304ae.value;
      }

      break;

    default:
      if (_0xfbaebd > 0) {
        if (_0x2304ae.value + 2 > mByteWidth) return false;
        _0x89c592[_0x2304ae.value] = _0xfbaebd | 192;
        ++_0x2304ae.value;
        _0x89c592[_0x2304ae.value] = _0x1c8c60;
        ++_0x2304ae.value;
      }

      break;
  }

  return true;
}

function calcRLEC(_0x2f1887, _0x134a27, _0x5898ba) {
  if (_0x134a27 <= 0) return 0;
  let _0x3ce86b = {
    "value": 0
  };
  let _0x907af0 = _0x2f1887[0];
  let _0x378250 = 1;

  for (let _0x58a55a = 1; _0x58a55a < _0x134a27; ++_0x58a55a) {
    if (_0x2f1887[_0x58a55a] === _0x907af0) {
      ++_0x378250;
    } else {
      if (!appendRLEC(_0x5898ba, _0x3ce86b, _0x907af0, _0x378250)) return 0;
      _0x907af0 = _0x2f1887[_0x58a55a];
      _0x378250 = 1;
    }
  }

  if (!appendRLEC(_0x5898ba, _0x3ce86b, _0x907af0, _0x378250)) return 0;
  return _0x3ce86b.value;
}

function pushRLEXD(_0x5cce33, _0x51ff98, _0x4c640) {
  if (_0x4c640 <= 0) return;
  let _0x456a1e = [31, _0x5cce33, 0];

  let _0x3ba060 = pushEBV(_0x456a1e, 2, _0x4c640);

  let _0x5507c6 = Math.floor((_0x4c640 * 5 + 7) / 8);

  pushPackage2(_0x456a1e, 0, _0x3ba060, _0x51ff98, 0, _0x5507c6);
}

function appendRLEXD(_0x56200d, _0x365a2e, _0x55c5dd, _0x3ba542) {
  if (_0x3ba542 <= 0) return true;

  let arIndex = Math.floor(_0x365a2e.value * 5 / 8);

  let _0x29381e = 15;

  while (_0x3ba542 > 0) {
    if (_0x3ba542 >= SuperBitmapRLELength[_0x29381e]) {
      _0x3ba542 -= SuperBitmapRLELength[_0x29381e];

      let _0x5a6bbe = _0x29381e | (_0x55c5dd ? 16 : 0);

      _0x365a2e.value = _0x365a2e.value + 1;
      if (_0x365a2e.value * 5 > mByteWidth * 8) return false;

      switch (_0x365a2e.value & 7) {
        case 0:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe;
          ++arIndex;
          break;

        case 1:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe << 3;
          break;

        case 2:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe >>> 2;
          ++arIndex;
          _0x56200d[arIndex] = _0x56200d[arIndex] | (_0x5a6bbe & 3) << 6;
          break;

        case 3:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe << 1;
          break;

        case 4:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe >>> 4;
          ++arIndex;
          _0x56200d[arIndex] = _0x56200d[arIndex] | (_0x5a6bbe & 15) << 4;
          break;

        case 5:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe >>> 1;
          ++arIndex;
          _0x56200d[arIndex] = _0x56200d[arIndex] | (_0x5a6bbe & 1) << 7;
          break;

        case 6:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe << 2;
          break;

        case 7:
          _0x56200d[arIndex] = _0x56200d[arIndex] | _0x5a6bbe >>> 3;
          ++arIndex;
          _0x56200d[arIndex] = _0x56200d[arIndex] | (_0x5a6bbe & 7) << 5;
          break;
      }
    } else {
      --_0x29381e;
    }
  }

  return true;
}

function calcRLEX(_0x8c3a24, _0x1d5d02, _0x15f0ac) {
  if (_0x1d5d02 <= 0) return 0;
  let _0xb626a7 = 0;
  let _0x4369cc = 0;
  let _0xc6c367 = false;
  let _0xbf69cd = 128;
  let _0x4f09b2 = {
    "value": 0
  };

  while (true) {
    if ((_0x8c3a24[_0x4369cc] & _0xbf69cd) !== 0) {
      if (_0xc6c367) {
        ++_0xb626a7;
      } else {
        if (!appendRLEXD(_0x15f0ac, _0x4f09b2, false, _0xb626a7)) return 0;
        _0xc6c367 = true;
        _0xb626a7 = 1;
      }
    } else {
      if (_0xc6c367) {
        if (!appendRLEXD(_0x15f0ac, _0x4f09b2, true, _0xb626a7)) return 0;
        _0xc6c367 = false;
        _0xb626a7 = 1;
      } else {
        ++_0xb626a7;
      }
    }

    if (_0xbf69cd === 1) {
      ++_0x4369cc;
      if (_0x4369cc >= _0x1d5d02) break;
      _0xbf69cd = 128;
    } else {
      _0xbf69cd = _0xbf69cd >>> 1;
    }
  }

  if (_0xc6c367 && !appendRLEXD(_0x15f0ac, _0x4f09b2, true, _0xb626a7)) return 0;
  return 0;
}

function calcRLED(_0x244c6e, _0x373f8c, _0x452094, _0xd0b7af, _0x58fa21) {
  let _0x3989fc = 0;
  let _0x1ba9ed = 0;
  let _0x38eb6e = false;
  let _0x1f26b8 = 128;
  let _0x156fba = {
    "value": 0
  };

  let _0x574199 = Math.min(_0x373f8c, _0xd0b7af);

  if (_0x574199 > 0) {
    while (true) {
      if ((_0x452094[_0x1ba9ed] & _0x1f26b8) !== (_0x244c6e[_0x1ba9ed] & _0x1f26b8)) {
        if (_0x38eb6e) {
          ++_0x3989fc;
        } else {
          if (!appendRLEXD(_0x58fa21, _0x156fba, false, _0x3989fc)) return 0;
          _0x38eb6e = true;
          _0x3989fc = 1;
        }
      } else {
        if (_0x38eb6e) {
          if (!appendRLEXD(_0x58fa21, _0x156fba, true, _0x3989fc)) return 0;
          _0x38eb6e = false;
          _0x3989fc = 1;
        } else {
          ++_0x3989fc;
        }
      }

      if (_0x1f26b8 === 1) {
        ++_0x1ba9ed;
        if (_0x1ba9ed >= _0x574199) break;
        _0x1f26b8 = 128;
      } else {
        _0x1f26b8 = _0x1f26b8 >>> 1;
      }
    }
  }

  if (_0x373f8c !== _0xd0b7af) {
    if (_0x373f8c < _0xd0b7af) {
      _0x244c6e = _0x452094;
      _0x373f8c = _0xd0b7af;
    }

    _0x1f26b8 = 128;

    while (true) {
      if (0 !== (_0x244c6e[_0x1ba9ed] & _0x1f26b8)) {
        if (_0x38eb6e) {
          ++_0x3989fc;
        } else {
          if (!appendRLEXD(_0x58fa21, _0x156fba, false, _0x3989fc)) return 0;
          _0x38eb6e = true;
          _0x3989fc = 1;
        }
      } else {
        if (_0x38eb6e) {
          if (!appendRLEXD(_0x58fa21, _0x156fba, true, _0x3989fc)) return 0;
          _0x38eb6e = false;
          _0x3989fc = 1;
        } else {
          ++_0x3989fc;
        }
      }

      if (_0x1f26b8 === 1) {
        ++_0x1ba9ed;
        if (_0x1ba9ed >= _0x373f8c) break;
        _0x1f26b8 = 128;
      } else {
        _0x1f26b8 = _0x1f26b8 >>> 1;
      }
    }
  }

  if (_0x38eb6e && !appendRLEXD(_0x58fa21, _0x156fba, true, _0x3989fc)) return 0;
  return _0x156fba.value;
}

function pushEBV(_0x37118b, _0x4c9d75, _0x15c04d) {
  if (_0x15c04d >= 192) {
    _0x37118b[_0x4c9d75 + 0] = _0x15c04d >>> 8 | 192;
    _0x37118b[_0x4c9d75 + 1] = _0x15c04d & 255;
    return _0x4c9d75 + 2;
  } else {
    _0x37118b[_0x4c9d75 + 0] = _0x15c04d;
    return _0x4c9d75 + 1;
  }
}

function pushPackage(_0x39276e) {
  pushPackage2(_0x39276e, 0, _0x39276e.length, null, 0, 0);
}

function pushPackage2(_0x573668, _0x5c4a2b, _0x149dd5, _0x2b9dd9, _0x53f3c4, _0x1b36e1) {
  let _0x80d435 = "";

  let ppIndex;

  let _0x264079;

  for (ppIndex = _0x5c4a2b; ppIndex < _0x149dd5; ++ppIndex) {
    _0x264079 = parseInt(_0x573668[ppIndex]);
    _0x264079 = _0x264079.toString(16);

    if ((_0x264079.length & 1) === 1) {
      _0x80d435 += "0" + _0x264079;
    } else {
      _0x80d435 += _0x264079;
    }
  }

  for (ppIndex = _0x53f3c4; ppIndex < _0x1b36e1; ++ppIndex) {
    _0x264079 = parseInt(_0x2b9dd9[ppIndex]);
    _0x264079 = _0x264079.toString(16);

    if ((_0x264079.length & 1) === 1) {
      _0x80d435 += "0" + _0x264079;
    } else {
      _0x80d435 += _0x264079;
    }
  }

  mArrayBitmap.push(_0x80d435);
}

module.exports = {
  "arrayWithImage": arrayWithImage,
  "arrayWithParam": arrayWithParam
};

function allocIntArray(allocIndex) {
  let _0x363101 = new Array(allocIndex);

  for (--allocIndex; allocIndex >= 0; --allocIndex) {
    _0x363101[allocIndex] = 0;
  }

  return _0x363101;
}

function checkArrayEquals(_0x60c8be, _0x2b3329, _0x585d09) {
  for (let i = 0; i < _0x585d09; ++i) {
    if (_0x60c8be[i] !== _0x2b3329[i]) return false;
  }

  return true;
}